package io.bdmc.common.wechatsdk;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.ConnectException;
import java.net.URL;
import java.net.URLEncoder;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.net.ssl.HttpsURLConnection;
import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import io.bdmc.common.utils.Constant;
import io.bdmc.common.utils.RedisUtils;;

/**
 * 公众平台通用接口工具类
 * 
 * @author huanglu
 * 
 */
@Component
public class WeChatUtil {

    @Resource
    private RedisUtils _redis;

    private static WeChatUtil factory;

    // 获取access_token的接口地址(GET) 限200次/天
    public final static String access_token_url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
    // 获取jsapi_ticket的接口地址(GET)
    public static String jsapi_ticket_url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi";
    
    protected static Logger logger = LoggerFactory.getLogger(WeChatUtil.class);

    @PostConstruct
    public void init() {
        factory = this;
    }

    /**
     * 发起https请求并获取结果
     * 
     * @param requestUrl    请求地址
     * @param requestMethod 请求方式(GET/POST)
     * @param outputStr     提交的数据
     * @return String(通过JSONObject.get(key)的方式获取json对象的属性值)
     */
    public static String httpRequest(String requestUrl, String requestMethod, String outputStr) {
        StringBuffer buffer = new StringBuffer();
        try {
            // 创建SSLContext对象，并使用我们指定的信任管理器初始化
            // TrustManager[] tm = { new MyX509TrustManager() };
            // SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
            // sslContext.init(null, tm, new java.security.SecureRandom());
            // 从上述SSLContext对象中得到SSLSocketFactory对象
            // SSLSocketFactory ssf = sslContext.getSocketFactory();

            URL url = new URL(requestUrl);
            HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();
            // httpUrlConn.setSSLSocketFactory(ssf);

            httpUrlConn.setDoOutput(true);
            httpUrlConn.setDoInput(true);
            httpUrlConn.setUseCaches(false);

            // 设置请求方式(GET/POST)
            httpUrlConn.setRequestMethod(requestMethod);
            if ("GET".equalsIgnoreCase(requestMethod))
                httpUrlConn.connect();

            // 当有数据需要提交时
            if (null != outputStr) {
                OutputStream outputStream = httpUrlConn.getOutputStream();
                // 注意编码格式,防止中文乱码
                outputStream.write(outputStr.getBytes("UTF-8"));
                outputStream.close();
            }

            // 将返回的输入流转换成字符串
            InputStream inputStream = httpUrlConn.getInputStream();
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);

            String str = null;
            while ((str = bufferedReader.readLine()) != null) {
                buffer.append(str);
            }
            bufferedReader.close();
            inputStreamReader.close();
            // 释放资源
            inputStream.close();
            inputStream = null;
            httpUrlConn.disconnect();
            return buffer.toString();
        } catch (ConnectException ce) {
            logger.info("Weixin server connection timed out.");
        } catch (Exception e) {
            logger.info("信任管理器请求超时时..." + e);
        }
        return "";
    }

 

 

    /**
     * 获取access_token (7200秒有效期)
     * 
     * @param appid     凭证
     * @param appsecret 密钥
     * @return
     */
    public static AccessToken getAccessToken() {
        AccessToken accessToken = null;

        String tk = factory._redis.get("AccessToken");
        if (tk != null && tk.length() > 1) {
            accessToken = new AccessToken();
            accessToken.setToken(tk);
            return accessToken;
        }
        String requestUrl = access_token_url.replace("APPID", Constant.APPID).replace("APPSECRET", Constant.APPSECRET);
        JSONObject jsonObject = JSONObject.parseObject(httpRequest(requestUrl, "GET", null));
        // 如果请求成功
        if (null != jsonObject) {
            try {
                accessToken = new AccessToken();
                accessToken.setToken(jsonObject.getString("access_token"));
                accessToken.setExpiresIn(jsonObject.getIntValue("expires_in"));
                factory._redis.set("AccessToken", accessToken.getToken(), Long.valueOf(accessToken.getExpiresIn()));
            } catch (Exception e) {
                accessToken = null;
                // 获取token失败
                logger.info("获取token失败 errcode:{} errmsg:{}" + jsonObject.getIntValue("errcode")
                        + jsonObject.getString("errmsg"));
            }
        }
        return accessToken;
    }

    /**
     * 获取jsapi_ticket（jsapi_ticket的有效期为7200秒）
     * 
     * @param token
     * @return
     */
    public static Ticket getTicket(String token) {
        Ticket ticket = null;
        String requestUrl = jsapi_ticket_url.replace("ACCESS_TOKEN", token);
        JSONObject jsonObject = JSONObject.parseObject(httpRequest(requestUrl, "GET", null));
        // 如果请求成功
        if (null != jsonObject) {
            try {
                ticket = new Ticket();
                ticket.setTicket(jsonObject.getString("ticket"));
                ticket.setExpiresIn(jsonObject.getIntValue("expires_in"));
            } catch (Exception e) {
                ticket = null;
                // 获取token失败
                logger.info("获取ticket失败 errcode:{} errmsg:{}" + jsonObject.getIntValue("errcode")
                        + jsonObject.getString("errmsg"));
            }
        }
        return ticket;
    }

    public static String CreateRedirect(String rurl) {
        try {
            return "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + Constant.APPID + "&redirect_uri="
                    + URLEncoder.encode(rurl, "utf-8") + "&scope=snsapi_userinfo&response_type=code&state=STATE";
        } catch (UnsupportedEncodingException e) {
            return "";
        }
    }

    public static OAuthUser GetOauthUser(String code) {
        OAuthToken token = GetOauthToken(code);
        OAuthUser user = GetWXUserInfo(token.getAccess_token(), token.getOpenid());
        return user;
    }

    private static OAuthToken GetOauthToken(String code) {
        String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + Constant.APPID + "&secret="
                + Constant.APPSECRET + "&code=" + code + "&grant_type=authorization_code";
        String result = httpRequest(url, "GET", null);
        OAuthToken oAuthToken = JSONObject.parseObject(result, OAuthToken.class);
        return oAuthToken;
    }

    private static OAuthUser GetWXUserInfo(String token, String openid) {
        String url = "https://api.weixin.qq.com/sns/userinfo?access_token=" + token + "&openid=" + openid;
        String result = httpRequest(url, "GET", null);
        OAuthUser oauser = JSONObject.parseObject(result, OAuthUser.class);
        return oauser;
    }

    public static JSONObject getSign(String url) {
        AccessToken token = getAccessToken();
        Ticket tick = getTicket(token.getToken());
        JSONObject sign = SignUtil.getSignature(Constant.APPID, tick.getTicket(), url);
        return sign;
    }

    public static String downloadImage(String media_id) {
        // 获取accesstoken（可根据情况自行获取accesstoken）
        AccessToken token = getAccessToken();
        String url = "https://api.weixin.qq.com/cgi-bin/media/get?access_token=" + token.getToken() + "&media_id="
                + media_id;
        RestTemplate restTemplate = new RestTemplate();
        // 进行网络请求,访问url接口
        ResponseEntity<byte[]> responseEntity = restTemplate.exchange(url, HttpMethod.GET, null, byte[].class);
        // 解析返回值（请求成功返回图片二进制流，失败返回错误信息json）
        if (responseEntity != null && responseEntity.getStatusCode() == HttpStatus.OK) {
            byte[] sessionData = responseEntity.getBody();
            try {
                for (int i = 0; i < sessionData.length; ++i) {
                    if (sessionData[i] < 0) {// 调整异常数据
                        sessionData[i] += 256;
                    }
                }

                File path = new File(Constant.EXPORTPATH);
                if (!path.exists()) {
                    path.mkdir();
                }
                // 生成jpg图片
                String savePath = path.getAbsolutePath() + "/image/";// 新生成的图片
                File path1 = new File(savePath);
                if (!path1.exists()) {
                    path1.mkdir();
                }
                // 根据内容类型获取扩展名
                String fileExt = responseEntity.getHeaders().getContentType().getSubtype();
                // 将mediaId作为文件名
                String filePath = savePath + media_id + "." + fileExt;
                OutputStream out = new FileOutputStream(filePath);
                out.write(sessionData);
                out.flush();
                out.close();
                String serverPath = "/image/" + media_id + "." + fileExt;
                return serverPath;
            } catch (Exception e) {
                System.out.println(e.getMessage());
                return null;
            }
        } else {
            return null;
        }

    }



}
